
#ifndef _MSC_H_
#define _MSC_H_

#include "compiler.h"

#define CBW_SIGNATURE  0x43425355
#define CBW_SIGNATURE_OPE 0x55534243
#define CSW_SIGNATURE  0x53425355

#define CBW_DIR_IN     0x80
#define CBW_DIR_OUT    0x00

#define CSW_STATUS_PASS 0x00
#define CSW_STATUS_FAIL 0x01
#define CSW_STATUS_PE   0x02

#define CBW_LEN 31
#define CSW_LEN 13

#define BOT_NO_CMD         0
#define BOT_CBW_RECEIVED   1
#define BOT_CBW_ERROR      2


#define MSC_TEST_UNIT_READY             0x00
#define MSC_REQUEST_SENSE               0x03
#define MSC_INQUIRY                     0x12
#define MSC_START_STOP_UNIT             0x1b
#define MSC_ALLOW_MEDIUM_REMOVAL        0x1e
#define MSC_MODE_SENSE6                 0x1a
#define MSC_MODE_SENSE10                0x5a
#define MSC_READ_FORMAT_CAPACITY        0x23
#define MSC_READ_CAPACITY               0x25
#define MSC_READ                        0x28
#define MSC_WRITE                       0x2a
#define MSC_VERIFY                      0x2f

#define CUSTOM_GET_SPACE_IDX        0xc1
#define CUSTOM_GET_BATTERY_POWER    0xc2
#define CUSTOM_UPDATE               0xc3
#define CUSTOM_UPDATE_COMPLETE      0xc4
#define CUSTOM_JUMP                 0xc5
#define CUSTOM_GET_CONTACT_INFO     0xc6
#define CUSTOM_SET_CONTACT_INFO     0xc7

#define CUSTOM_GET_DEV_STATUS       0xc8
#define CUSTOM_MODIFY_PWD           0xc9
#define CUSTOM_MODIFY_EMAIL         0xca
#define CUSTOM_CLOSE_PROTECT        0xcb
#define CUSTOM_VERIFY_PWD           0xcc
#define CUSTOM_ALT_PC_MODE          0xcd
#define CUSTOM_GET_PWD_EMAIL        0xce

#define CUSTOM_GET_PROTECT_CMD_STATUS  0xd1

#define PRIVATE_GET_VERSION          0xf0
#define PRIVATE_FORCE_BOOT           0xf1
#define PRIVATE_GET_CRC              0xf2
#define PRIVATE_GET_CODE             0xf3
#define PRIVATE_ERASE_ALL_PROTECT    0xf4
#define PRIVATE_GET_DEVICE_ID        0xf5

#define INVALID_CDB                                 0x20
#define INVALID_FIELED_IN_COMMAND                   0x24
#define PARAMETER_LIST_LENGTH_ERROR                 0x1A
#define INVALID_FIELD_IN_PARAMETER_LIST             0x26
#define ADDRESS_OUT_OF_RANGE                        0x21
#define MEDIUM_NOT_PRESENT                          0x3A
#define MEDIUM_HAVE_CHANGED                         0x28
#define WRITE_PROTECTED                             0x27 
#define UNRECOVERED_READ_ERROR			    0x11
#define WRITE_FAULT				    0x03

#define REQUEST_SENSE_DATA_LEN                      0x12
#define INQUIRY_DATA_LEN                            0x24
#define FORMAT_CAPACITY_LEN                         0x0c
#define CAPACITY_LEN                                0x08


#define  SECTOR_SIZE                 512
#define  PINGPONG_BUFFER_SIZE        (SECTOR_SIZE * 30)


typedef enum
{
    NO_SENSE = 0,
    RECOVERED_ERROR = 1,
    NOT_READY,
    MEDIUM_ERROR,
    HARDWARE_ERROR,
    ILLEGAL_REQUEST,
    UNIT_ATTENTION,
    DATA_PROTECT,
    BLANK_CHECK,
    VENDOR_SPECIFIC,
    COPY_ABORTED,
    ABORTED_COMMAND,
    VOLUME_OVERFLOW,
    MISCOMPARE,
}sense_enum;

COMPILER_PACK_SET(1)
typedef struct
{
    uint32_t dCBWSignature;
    uint32_t dCBWTag;
    uint32_t dCBWDataTransferLength;
    uint8_t  bmCBWFlags;
    uint8_t  bCBWLUN;
    uint8_t  bCBWCBLength;
    uint8_t  CDB[16];
    uint8_t  reserved[512 - 35];  
    uint32_t dCBWsignope;
}msc_cbw_t;

typedef struct
{
    uint32_t dCSWSignature;
    uint32_t dCSWTag;
    uint32_t dCSWDataResidue;
    uint8_t  bCSWStatus;
    uint8_t  reserved[3];
}msc_csw_t;

COMPILER_PACK_RESET()

typedef struct 
{
    uint8_t cmd;
    bool   (*process_ptr)(void);
}cbw_process_t;

typedef struct
{                
    uint8_t s_key;
    union 
    {
        struct _ASCs 
        {
            uint8_t ASC;
            uint8_t ASCQ;
        }b;
        uint16_t ASC;
        uint8_t *data_ptr;
    } w;
} scsi_sense_t; 

typedef struct
{
    uint8_t *p_ping_buf_ptr;
    uint8_t *p_pong_buf_ptr;
    bool b_ping_flag;
}ping_pong_t;

extern uint32_t        blk_size;
extern uint32_t        blk_nbr;
extern uint32_t        blk_addr;
extern uint32_t        blk_len;
extern ping_pong_t     ping_pong;
extern uint8_t msc_bulk_buffer[(PINGPONG_BUFFER_SIZE * 2)];

uint8_t bot_get_cbw(bool b_pc);
bool bot_cmd_process(void);
void bot_send_csw(void);
void update_sense_code(uint8_t s_key, uint8_t ASC);
void send_bot_data_in(void);
void receive_bot_data_out(void);
bool msc_process(bool b_pc);

uint8_t get_pc_contact_flag(void);
uint8_t get_iphone_id(uint8_t *id_buff);
void set_pc_contact_flag(uint8_t flag);
void set_iphone_id(uint8_t *id_buff, uint8_t id_len);

#endif
